package org.dxy.infrastructure.adapter.repository;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.dxy.domain.port.IEventRepository;
import org.dxy.domain.event.DomainEvent;
import org.dxy.infrastructure.persistent.db.mybatispuls.po.DomainEventPo;
import org.dxy.infrastructure.persistent.db.mybatispuls.service.DomainEventService;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @ description:
 * @ author: dxy
 * @ createTime: 2025/7/14 23:51
 */
@Repository
@RequiredArgsConstructor
public class EventRepository implements IEventRepository {
    private final DomainEventService  domainEventService;
    private final ObjectMapper objectMapper;

    @Override
    public List<Long> saveEvents(List<DomainEvent> events) {
        if (CollectionUtils.isEmpty(events)) {
            return List.of();
        }

        // 所有事件属于同一个聚合
        Long aggregateId = events.get(0).aggregateId();

        boolean allSameAggregate = events.stream()
                .allMatch(e -> aggregateId.equals(e.aggregateId()));

        if (!allSameAggregate) {
            throw new IllegalArgumentException("事件列表中包含不同聚合的事件");
        }

        // 1. 查询当前最大 index
        Integer maxIndex = domainEventService.findMaxIndexByAggregateId(aggregateId);
        if (maxIndex == null) {
            maxIndex = 0;
        }

        // 2. 给事件列表赋 index，并固定事件ID
        List<DomainEventPo> entities = new ArrayList<>();
        List<Long> eventIds = new ArrayList<>();
        int currentIndex = maxIndex;
        
        for (DomainEvent event : events) {
            currentIndex++;
            // 固定事件ID，避免重复生成
            Long eventId = event.eventId();
            eventIds.add(eventId);

            DomainEventPo entity = null;
            try {
                entity = DomainEventPo.builder()
                        .id(eventId)
                        .aggregateId(aggregateId)
                        .aggregateType(event.aggregateType())
                        .eventType(event.eventType())
                        .eventData(objectMapper.writeValueAsString(event))
                        .occurredAt(LocalDateTime.now())
                        .eventIndex(currentIndex)
                        .source(event.source())
                        .published(false)
                        .build();
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
            entities.add(entity);
        }
        
        // 3. 批量插入
        boolean success = domainEventService.saveBatch(entities);
        if (success) {
            return eventIds;
        } else {
            throw new RuntimeException("保存事件失败");
        }
    }

    @Override
    public boolean markEventsPublished(List<Long> eventIds) {
        return domainEventService.markEventsPublished(eventIds);
    }
}
